\documentclass[a4paper,12pt]{article}

\usepackage[margin=1.5cm]{geometry}
\usepackage{listings}
\usepackage{enumitem}

\title{How Function Arguments Are Dealt With in C}
\author{Chen Rushan\\chenrsster@gmail.com}
\date{2009.08.24 03:37}

\setlength{\parskip}{1.2ex}
\setlength{\parindent}{0pt}

\newcounter{expcnter}

\lstset{
    frame=single, framesep=0pt, framexleftmargin=-1pt, framextopmargin=3pt,
    framexbottommargin=3pt, aboveskip=0.5cm, belowskip=0.2cm, columns=flexible,
    basicstyle=\ttfamily
}

\begin{document}

\maketitle

\section{Some confusing examples}

    \label{sec:examples}

    Before we present how function arguments are dealt with in C, let's first
    see some confusing examples:
    
    \refstepcounter{expcnter}
    \label{exp:floatchar}
    {\bf \em Example \theexpcnter:}
    
    Consider a program consisting of the following 2 files: (All the header
    files needed for the programs presented in this article will be omitted to
    save space)
    
    {\em file1.c:}

    \begin{lstlisting}[gobble=3]
    void print_float_out(float flt, char ch)
    {
            printf("%f %c\n", flt, ch);
    }
    \end{lstlisting}
    
    {\em file2.c:}

    \begin{lstlisting}[gobble=3]
    int main(int argc, char **argv)
    {
            float f = 39887.0078125;
            char c = 'a';
            print_float_out(f, c);
            return 0;
    }
    \end{lstlisting}
    
    The expected result of this program is:

    \begin{lstlisting}[gobble=3]
    39887.0078125 a
    \end{lstlisting}

    However, the real result is:

    \begin{lstlisting}[gobble=3, escapechar=\%]
    2.000000 %$\hat{a}$%
    \end{lstlisting}
    
    Eh! What happened, everything seems right, what converted my 39887.0078125
    to 2.000000, and why there's a hat on my {\tt a}.
    
    \newpage

    \refstepcounter{expcnter}
    \label{exp:longlong}
    {\bf \em Example \theexpcnter:}

    Now consider this program which consists of the following 2 files:

    {\em file1.c}

    \begin{lstlisting}[gobble=3]
    void print2ints(int i1, int i2)
    {
            printf("0x%x 0x%x\n", i1, i2);
    }
    \end{lstlisting}
    
    {\em file2.c}

    \begin{lstlisting}[gobble=3]
    int main(int argc, char **argv)
    {
            long long ll = 0x1111111122222222;
    
            print2ints(ll);
    
            return 0;
    }
    \end{lstlisting}
    
    The output of this program is:

    \begin{lstlisting}[gobble=3]
    0x22222222 0x11111111
    \end{lstlisting}

    You may even think a program like this can't be correctly complied, but the
    truth is it can, so why, and why the output looks like this?

    \refstepcounter{expcnter}
    \label{exp:charchar}
    {\bf \em Example \theexpcnter:}

    Now consider another confusing program which consists of these 2 files:

    {\em file1.c}
     
    \begin{lstlisting}[gobble=3, aboveskip=0.3cm]
    void print_char(char c1, char c2)
    {
            printf("print_char:  %p %p\n", &c1, &c2);
    }
    
    void print_float(float f1, float f2)
    {
            printf("print_float: %p %p\n", &f1, &f2);
    }
    \end{lstlisting}

    {\em file2.c}

    \begin{lstlisting}[gobble=3]
    int main(int argc, char **argv)
    {
            print_char('c', 'd');
            print_float(1.5, 1.2);
    
            return 0;
    }
    \end{lstlisting}

    And the output of this program is: (you may get different results, due to
    the different stack position each time you run your program)

    \begin{lstlisting}[gobble=3]
    print_char:  0xbfb1768c 0xbfb17688
    print_float: 0xbfb176a0 0xbfb176a4
    \end{lstlisting}

    Now you might wonder why the addresses output by \verb=print_char= is in
    descending order, whereas addresses output by \verb=print_float= is in
    ascending order. Rather confusing, Right?

    Section ends here, you may be rather rather confused now, I'll uncover all
    the secrets below.

\section{Things happen when no function declaration is given}
    
    In C, if there's no declaration before calling a function, then the
    following two things will happen: (Note that placing the function
    definition in the same file as but before where it's called also means it's
    declared)

    {
    \setlength{\parskip}{0pt}
    \begin{enumerate}
        \item You're allowed to call this function with whatever arguments you
            like. It doesn't matter whether the number of arguments match the
            number of parameters given in function definition, nor does it
            matter whether the types of the arguments match.

        \item Arguments will always be promoted before they are passed to
            this function. So {\tt char} will always be promoted to {\tt int},
            {\tt short} to {\tt int} too, and {\tt float} to {\tt double} and
            so on.
    \end{enumerate}

    Now let's begin talking things in further detail.
    }

    \subsection{No declaration, no error checking}

    If you've no idea about how stack and corresponding registers change when a
    function is called, it's recommended that you read {\tt Appendix
    \ref{app:stackchange}} before you move on.

    As we mentioned above, without declaration, you're free to pass anything to
    a function, even nothing. Why? Because in that case, no check will be
    performed on use against function definition, and as long as the name of
    the function you call appears in the table of all functions, no error will
    be issued, then you may wonder what the function arguments will be in such
    cases, the answer is whatever is found on the stack.

    % TODO here

    Now let's consider example \ref{exp:longlong} in section
    \ref{sec:examples} again where we call a
    function named {\em print2ints} which expects two {\tt int} data with a
    {\tt long long} data. Here's what happens under the hood:

    {
    \setlength{\parskip}{0pt}
    \begin{enumerate}
        \item Before function {\em print2ints} is executed, its argument
            is first pushed onto the stack, here {\em ll} is the argument, so
            the stack will be:

            \begin{lstlisting}[frame=lines, escapechar=\%, gobble=11]
            ... ...
            11
            11
            11
            11
            22
            22
            22
            22
            Return address          %{\rm $\longleftarrow$ \%esp}%
            \end{lstlisting}

        \item Since {\em print2ints} expects two {\tt int} as its arguments, it
            just scans the stack from {\tt \%ebp + 8} up (Note that {\tt
            \%ebp + 8} is where the arguments of a function begin), assigns
            bytes from {\tt (\%ebp + 8)} to {\tt (\%ebp + 12)} to the 1st
            argument, which happens to be 0x22222222 here, and assigns bytes
            from {\tt (\%ebp + 12)} to {\tt (\%ebp + 16)} to the 2nd argument,
            which is 0x11111111.
    \end{enumerate}
    }

    There is still one point you need to pay attention to . The declaration is
    allowed to be different than the actual definition when they appear in
    different files, that's why it's important to include the header file into
    the function definition file, that will force complier to check the
    declaration against definition.

    \subsection{Argument promotion}

    For information about the assembly instructions involved in this section,
    refer to {\tt Appendix \ref{app:asm}}.

    Before talking about {\em argument promotion}, we first talk about {\em
    type promotion}, which is a relatively wider concept.

    Consider the following simple example:

    \begin{lstlisting}[gobble=3]
    char c1 = 'a', c2 = 'b';
    c1 = c1 + c2;
    \end{lstlisting}

    This code snippet corresponds to the following assembly code: (Note that
    \verb=61 62= are just offsets, which vary in different situations, I
    compiled the above code using \verb=gcc -S= without optimization)

    \begin{lstlisting}[gobble=3]
    movb    $97, 61(%esp)
    movb    $98, 62(%esp)
    movzbl  61(%esp), %edx
    movzbl  62(%esp), %eax
    leal    (%edx,%eax), %eax
    movb    %al, 61(%esp)
    \end{lstlisting}

    From above, we find that {\em c1} and {\em c2} are first zero-expanded to
    be 4 bytes long (on 32-bit architecture), storing in {\em \%edx} and {\em
    \%eax} respectively, then two registers are added together, and finally the
    result is truncated and stored into memory again. In this example, the
    so-called {\em type promotion} happens when {\em c1} and {\em c2} get
    zero-expanded.

    According to the ANSI C standard, {\em type promotion} is not necessary if
    the result would be the same without type promotion, so the calculation in
    the previous example can actually be accomplished without expansion, I
    think the reason why the two chars get expanded is that it's much easier to
    code that way, the following table lists commonly-seen type promotion:

    \begin{center}
    \begin{tabular}{|p{5cm}|p{5cm}|}
    \hline
    \multicolumn{1}{|c|}{Original Type} & \multicolumn{1}{c|}{Promoted To} \\
    \hline
    char & int \\\hline
    short & int \\\hline
    float & double \\\hline
    unsigned char & int \\\hline
    unsigned short & int \\\hline
    \end{tabular}
    \end{center}

    Type promotion also applies to function arguments(since argument is also
    expression), and in this case, we call it {\em argument promotion}. As we
    mentioned above, when there's no declaration, argument promotion always
    happens. With all these in mind, it's time to unlock the mystery behind
    example \ref{exp:floatchar} in section \ref{sec:examples}. Before you
    proceed, you'd better have a little idea about how a floating point number
    is represented in memory, if you've no idea, refer to \textbf{Appendix
    \ref{app:float}} first.

    The first 3 lines of main function corresponds to the following assembly
    code:

    \begin{lstlisting}[gobble=3]
    movl    $0x471bcf02, %eax
    movl    %eax, 24(%esp)
    movb    $97, 31(%esp)
    movsbl  31(%esp),%eax
    flds    24(%esp)
    movl    %eax, 8(%esp)
    fstpl   (%esp)
    call    print_float_out
    \end{lstlisting}

    From above, we can find how float data {\em f} is handled, it's first
    stored into memory location {\em 24(\%esp)}, then pushed onto the FPU
    stack, and finally popped to location {\em (\%esp)}. It's the final step
    where the argument promotion happens, note that when pushing, we push a
    single-precision number, but when popping, we popes a double-precision
    number, which causes the single-precision number to be expanded to be a
    double-precision number(0x471bcf02 $\longrightarrow$ 0x40e379e040000000),
    so argument {\em f} occupies 8 bytes on the stack, and argument {\em c} is
    stored from location {\em 9(\%esp)} up. 
    
    After arguments are in the right places, function {\em print\_float\_out} is
    called, which expects a 4-byte long float data, and a 1-byte long char
    data(actually also 4-byte long, but only the 1st byte will be used), causing
    the first 4 bytes 0x40000000 to be assigned to parameter {\em flt}, making
    {\em flt} equals to 2.000000, the next 4 bytes 0x40e379e0 to parameter {\em
    ch}, making {\em ch} equals to 0xe0, or $\hat{a}$. Now you know what
    converts 39887.0078125 to 2.000000, and why there's a hat on {\tt a}.

    \subsection{How to avoid previous errors}

    In order to keep previous errors from happening, the solution is rather
    simple, just add declaration before you call a function(defining a function
    before you use it automatically add declaration). So to make example
    \ref{exp:floatchar} behave as expected, modify {\em file2.c} to be:

    \begin{lstlisting}[gobble=3]
    void print_float_out(float, char);

    int main(int argc, char **argv)
    {
            float f = 39887.0078125;
            char c = 'a';
            print_float_out(f, c);
            return 0;
    }
    \end{lstlisting}

    Now you may find out why header file is so important.

    Note that even if you add declaration, argument promotion may happen, but
    it's guaranteed that everything works correctly. So the rule of thumb is:

    \begin{lstlisting}[gobble=3, escapechar=\%]
    %\centerline{\bf \em Always add declaration before calling functions!!!}%
    \end{lstlisting}

    \textbf{P.S.}

    Whether you add a declaration of a function has nothing to do with the final
    code of that function, it just affects the way in which the caller pass
    arguments.

    \begin{enumerate}[topsep=0pt, leftmargin=3ex]
        \item A char argument costs 4 btyes.
        \item A short argument costs 4 btyes.
    \end{enumerate}

    \section{Misc}

    Example \ref{exp:charchar} in section \ref{sec:examples} hasn't been
    discussed yet. As we all know, function arguments are pushed on the stack in
    reverse order that 1st argument is pushed last and the last argument is
    pushed first, so why the output of function {\em print\_char} in that
    example show us different order. The answer is quite simple: because the
    addresses you output are not the addresses of the real arguments.

    You can find this by converting the C source code into assembly code. The
    function {\em print\_char} corresponds to:

    \begin{lstlisting}[gobble=3]
    .LC0:
        .string "print_char:  %p %p\n"
        .text
    .globl print_char
        .type   print_char, @function
    print_char:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $40, %esp
        movl    8(%ebp), %edx
        movl    12(%ebp), %eax
        movb    %dl, -12(%ebp)
        movb    %al, -16(%ebp)
        movl    $.LC0, %eax
        leal    -16(%ebp), %edx
        movl    %edx, 8(%esp)
        leal    -12(%ebp), %edx
        movl    %edx, 4(%esp)
        movl    %eax, (%esp)
        call    printf
        leave
        ret
    \end{lstlisting}

    From above, it's easy to find that {\em c1} and {\em c2} are first fetched
    from the area storing arguments, and then stored into another area, with
    {\em c1} to location {\em -12(\%ebp)}, c2 to {\em -16(\%ebp)}, and what
    \verb=printf= prints are these two new address, since $-12 > -16$, we got
    the output addresses in reverse order as expected.

\newpage
\appendix

\section*{Appendix}

    \section{How does float and double data store in memory}
    \label{app:float}

    \subsection{Storage layout}

    IEEE standard 754 floating point is the most common representation today
    for real numbers in computers ({\em float} here means the point is not
    fixed). Basically, an IEEE floating point number consist of three parts:
    {\bf sign}, {\bf exponent}, {\bf mantissa}. The following table shows the
    number of bits each field contains for single and double precision floating
    point numbers (bit ranges are in square brackets):

    \begin{center}
    \begin{tabular}{|r|c|c|c|}
    \hline
    & sign & exponent & mantissa \\
    \hline
    single precision & 1[31] & 8[30-23] & 23[22-0] \\
    \hline
    double precision & 1[63] & 11[62-52] & 52[51-0] \\
    \hline
    \end{tabular}
    \end{center}

    \begin{enumerate}[leftmargin=3ex, itemsep=0pt]
        \item {\bf sign bit}

            0 denotes a positive number, 1 a negative number.

        \item {\bf exponent}

            In order to represent both positive and negative exponent, a {\em
            bias} is added to the actual exponent, which results in a stored
            exponent. For single precision floating point number, the bias is
            127, so an exponent of 0 is stored in memory as 127, and a stored
            value of 200 is actually an exponent of (200-127), or 73. Exponents
            of -127 and 128 are reserved for special reasons.

            For double precision, the bias is 1023.

        \item {\bf mantissa}

            It's composed of a implicit leading bit which is 1 and the fraction
            bits.
    \end{enumerate}

    \subsection{Examples:}

    Here I present some examples to illustrate how each field of a floating
    point number is generated (Examples below only show you how to convert
    numbers to single precision representation, for double precision
    representation, the process is similar).
    
    \setcounter{expcnter}{0}
    \refstepcounter{expcnter}
    {\bf \em Example \theexpcnter:}

    Consider number $-1313.3125$:
    \begin{enumerate}[itemsep=0pt]
        \item Getting the sign bit is trivial. Just glancing at the number, we
            know the bit is 1.

        \item Getting the exponent and mantissa involves somewhat complicated
            calculation:

            \begin{enumerate}
                \item The integral part is $1313_{10}=10100100001_2$. The
                    fractional:

                    \parbox{1.5cm}{$0.3125$}\parbox{1cm}{$ * 2$}
                    \parbox{2cm}{$= 0.625$} \fbox{0} Generate 0 and continue.
                                                            \nopagebreak\\
                    \parbox{1.5cm}{$0.625$}\parbox{1cm}{$ * 2$}
                    \parbox{2cm}{$= 1.25$} \fbox{1} Generate 1 and continue
                                                with the rest.\nopagebreak\\
                    \parbox{1.5cm}{$0.25$}\parbox{1cm}{$ * 2$}
                    \parbox{2cm}{$= 0.5$} \fbox{0} Generate 0 and continue.
                                                            \nopagebreak\\
                    \parbox{1.5cm}{$0.5$}\parbox{1cm}{$ * 2$}
                    \parbox{2cm}{$= 1.0$} \fbox{1} Generate 1 and nothing
                                                            remains.

                    So $1313.3125_{10} = 10100100001.0101_{2}$

                \item Normalize: $10100100001.0101_{2}=1.01001000010101_2*
                                                                    2^{10}$

                \item So the mantissa is 01001000010101000000000, exponent is
                    $10 + 127 = 137 = 10001001_2$.
            \end{enumerate}
    \end{enumerate}

    So $-1313.3125$ is 
    \begin{tabular}{|c|c|c|}
    \hline 1 & 10001001 & 01001000010101000000000\\ \hline
    \end{tabular}.\\[0.1cm]

    \refstepcounter{expcnter}
    {\bf \em Example \theexpcnter:}

    Consider number $0.1015625$:
    \begin{enumerate}
        \item The sign bit is 0

        \item The mantissa and exponent fields:

            \begin{enumerate}
                \item Converting:

                    \parbox{2cm}{0.1015625}\parbox{1cm}{$* 2$}\parbox{2cm}{$=
                    0.203125$} \fbox{0} Generate 0 and continue.\nopagebreak\\
                    \parbox{2cm}{0.203125}\parbox{1cm}{$* 2$}\parbox{2cm}{$=
                    0.40625$} \fbox{0} Generate 0 and continue.\nopagebreak\\
                    \parbox{2cm}{0.40625}\parbox{1cm}{$* 2$}\parbox{2cm}{$=
                    0.8125$} \fbox{0} Generate 0 and continue.\nopagebreak\\
                    \parbox{2cm}{0.8125}\parbox{1cm}{$* 2$}\parbox{2cm}{$=
                    1.625$} \fbox{1} Generate 1 and continue with the
                    rest.\nopagebreak\\
                    \parbox{2cm}{0.625}\parbox{1cm}{$* 2$}\parbox{2cm}{$=
                    1.25$} \fbox{1} Generate 1 and continue with the
                    rest.\nopagebreak\\
                    \parbox{2cm}{0.25}\parbox{1cm}{$* 2$}\parbox{2cm}{$= 0.5$}
                    \fbox{0} Generate 0 and continue.\nopagebreak\\
                    \parbox{2cm}{0.5}\parbox{1cm}{$* 2$}\parbox{2cm}{$= 1.0$}
                    \fbox{1} Generate 1 and nothing remains.\nopagebreak\\
                    So 0.101562510 = 0.00011012.

                \item Normalize: $0.0001101_2 = 1.101_2 * 2^{-4}$
                \item Mantissa is 10100000000000000000000, exponent is
                    $-4+127=123=01111011_2$
            \end{enumerate}
    \end{enumerate}

    So $0.1015625$ is
    \begin{tabular}{|c|c|c|}
    \hline 0 & 01111011 & 10100000000000000000000\\ \hline
    \end{tabular}.

    {\bf P.S.}
    
    To print out the corresponding binary for a number, the following
    two methods can be used:

    \begin{itemize}
        \item Use {\tt x} command in {\tt gdb} as:

            \begin{lstlisting}[gobble=11, escapechar=\%]
            x/t %{\em <address-of-number>}%
            \end{lstlisting}

            Here {\tt /t} means printing the number in binary format.

        \item Write a function like this one:

            \begin{lstlisting}[gobble=11]
            void print_bit(char *x, int size)
            {
                    int i = 0, j = 0;
            
                    for (i = size - 1; i >= 0; i--) {
                            for (j = 7; j >=0; j--) {
                                    unsigned char t = *(x + i) & (1 << j);
                                    if (t > 0)
                                            printf("1");
                                    else
                                            printf("0");
                            }
                            printf(" ");
                    }
                    putchar('\n');
            }
            \end{lstlisting}
    \end{itemize}

    \section{What happens to stack when a C function is called}
    \label{app:stackchange}

    Here we'll talk everything in terms of assembly language (in ANSI syntax),
    so that we can thoroughly understand what exactly happens when a C function
    is called.

    \begin{enumerate}[leftmargin=3ex]
        \item First of all, all function arguments will be pushed onto the
            stack in the reverse order that they are documented, so the stack
            now looks like this:

            \begin{lstlisting}[frame=lines, gobble=11, escapechar=\%]
            parameter N
            ... ...
            parameter 2
            parameter 1         %{\rm $\longleftarrow$ \%esp}%
            \end{lstlisting}

        \item Then a {\tt call} instruction will be issued, two things are done
            here. First the address of the next instruction, that is the return
            address of this function is pushed onto the stack. Then the
            instruction pointer ({\em \%eip}) is modified to point to the start
            of this function. Now the stack looks like this:

            \begin{lstlisting}[frame=lines, gobble=11, escapechar=\%]
            parameter N
            ... ...
            parameter 2
            parameter 1
            return address      %{\rm $\longleftarrow$ \%esp}%
            \end{lstlisting}

        \item After all preparation is done, we now enter the function body,
            the first thing to do is make a backup of current base pointer
            register {\em \%ebp}, which is generally used to access the
            function arguments and local variables, and then copy current {\em
            \%esp} to {\em \%ebp}, which makes accessing function arguments and
            local variables very conveniently. So the first two instruction of
            a function are:

            \begin{lstlisting}[gobble=11]
            pushl   %ebp
            movl    %esp, %ebp
            \end{lstlisting}

            At this point, the stack looks like this:

            \begin{lstlisting}[frame=lines, gobble=11, escapechar=\=]
            parameter N
            ... ...
            parameter 2
            parameter 1
            return address      ={\rm $\longleftarrow$ 4(\%ebp)}=
            old %ebp            ={\rm $\longleftarrow$ \%esp, \%ebp}=
            \end{lstlisting}

        \item Suppose this function contains two local variables of {\tt int}
            type, then the instruction right after the previous two will be:
            (also assuming that you're on 32-bit platform)

            \begin{lstlisting}[gobble=11]
            subl 8, %esp
            \end{lstlisting}

            This reserves stack space for your local variables, and the stack
            will look like:
            
            \newpage
            \begin{lstlisting}[frame=lines, gobble=11, escapechar=\=]
            parameter N
            ... ...
            parameter 2
            parameter 1
            return address      ={\rm $\longleftarrow$ 4(\%ebp)}=
            old %ebp            ={\rm $\longleftarrow$ \%esp, \%ebp}=
            local var1          ={\rm $\longleftarrow$ $-$4(\%ebp)}=
            local var2
            \end{lstlisting}

        \item Now begin executing whatever is in your function body.

        \item After the function is done executing, it does three things:

            \begin{enumerate}
                \item It stores the return value in {\em \%eax}.

                \item It resets the stack back to what it was when it was
                    called.

                \item It returns the control back to whatever it was called
                    from. This is done using {\tt ret} instruction, which pops
                    whatever is at the top of the stack, and sets the
                    instruction pointer {\em \%eip} to that value.
            \end{enumerate}

            Obviously, for {\tt ret} to work, the return address should appear
            at the top of stack, to accomplish this, use {\em leave}
            instruction, which has the same effect as the following two
            instructions:

            \begin{lstlisting}[gobble=11]
            movl %ebp %esp
            popl %ebp
            \end{lstlisting}

            The second instruction above makes the return address to be at the
            top of the stack.
            
            Therefore, returning from a function involves the following steps:

            \begin{lstlisting}[gobble=11, escapechar=\=]
            movl ={\em sth}= %eax # left out if you don't have a return value
            leave
            ret
            \end{lstlisting}

    \end{enumerate}

    \section{Assembly Language instruction reference}

        \label{app:asm}

        \begin{itemize}[leftmargin=3ex]
            \item {\bf movz} 
            
                This instruction moves an unsigned integer to a larger unsigned
                integer with {\em zero extension}, source and destination in
                memory or register.({\bf movzbw} byte to word, {\bf movzbl}
                byte to long, {\bf movzwl} word to long).

            \item {\bf movs}

                This instruction is similar to the previous one except that
                data is moved with sign extension.

            \item {\bf leal}

                This instruction stores memory location given in the standard
                format into somewhere like register or another memory location.
                Before we talk about how this instruction works, we need first
                know how a memory location is represented. 

                The general form of a memory address is:
                \begin{lstlisting}[gobble=15]
                ADDRESS_OR_OFFSET(%BASE_OR_OFFSET, %INDEX, MULTIPLIER)
                \end{lstlisting}
                and the address generated is:
                \begin{lstlisting}[gobble=15]
                ADDRESS_OR_OFFSET + %BASE_OR_OFFSET + MULTIPLIER * %INDEX
                \end{lstlisting}

                \verb=ADDRESS_OR_OFFSET= and \verb=MULTIPLIER= here must both
                be constants, while the other two must be registers.

                So address \verb=5(%ebp, %ecx, 2)= points to the memory
                location \verb=5 + %ebp + %ecx * 2=, and if there's an
                instruction \verb=leal 5(%ebp, %ecx, 2) %eax=, it means store
                the above address into \verb=%eax= instead of storing the value
                located in that address into \verb=%eax=.

                Note that although this instruction is used to do address
                manipulation, it's also commonly used to perform basic
                arithmetic, an example would be \verb=leal (%edx, %eax), %eax=
                which adds two values in \verb=%edx= and \verb=%eax=, and 
                stores the final result into \verb=%eax=.

            \item {\bf fld}

                This instruction pushes a float number onto the FPU stack.
                {\bf flds} pushes a single-precision float number, while {\bf
                fldl} a double-precision.

            \item {\bf fstp}

                This instruction popes a float number from the top of the FPU
                stack. {\bf fstps} popes a single-precision float number, while
                {\bf fstpl} popes a double-precision float number.
        \end{itemize}

\end{document}

